import * as model from '@/model/index.ts'
import moment from 'dayjs'
// import { ImagePreview } from 'vant'
// import GDMap from '@/utils/map'
const jrQrcode = require('jr-qrcode')
import * as auth from '@/utils/auth'
import VConsole from 'vconsole'
export const sleep = (time) =>
  new Promise((resolve) => {
    setTimeout(resolve, time)
  })

// 懒加载组件
export const lazyComponent =
  (name, isIndex = true) =>
  () =>
    import(`@/views/${name}${isIndex ? '/index' : ''}.vue`)

export const lazyFie = (file) => () => import(`@/components/${file}`)

// 动态加载 js 文件
export const createScript = (obj = {}, el = 'head') => {
  const jsapi = document.createElement('script')
  for (const i in obj) {
    jsapi[i] = obj[i]
  }
  document[el].appendChild(jsapi)
  return new Promise((resolve) => {
    jsapi.onload = () => {
      resolve()
    }
  })
}

// 拷贝对象
export const deep = (obj) => JSON.parse(JSON.stringify(obj))

export function param2Obj(url) {
  url = url || window.location.search

  let search = url.split('?')[1]
  if (!search) {
    return {}
  } else {
    search = search.replace(/#\//g, '')
  }

  // 为了不去验证是否兼容以往的逻辑 所做的 try catch 扩展
  try {
    return JSON.parse(
      '{"' +
        decodeURIComponent(search)
          .replace(/"/g, '\\"')
          .replace(/&/g, '","')
          .replace(/=/g, '":"')
          .replace(/\+/g, ' ') +
        '"}'
    )
  } catch (error) {
    return param2Obj1(url)
  }
}

export function param2Obj1(url) {
  const search = url.split('?')[1]
  if (!search) {
    return {}
  }
  const array = search.split('&')
  const obj = {}
  array.forEach((item) => {
    const as = item.split('=')
    const k = as[0] || ''
    const v = as[1] || ''
    obj[k] = v
  })
  if (obj.backUrl) {
    obj.backUrl = decodeURIComponent(obj.backUrl)
  }
  return obj
}

export function obj2Param(obj = {}) {
  const param = []
  for (const i in obj) {
    const str = `${i}=${obj[i]}`
    param.push(str)
  }
  return param.join('&')
}

export const eachOwn = (obj, fn) => {
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      fn(obj[key], key, obj)
    }
  }
}

// 节流模式 （业务逻辑只执行最后一次）
export const throttle = (fn, args = [], that = this, time = 300) => {
  fn._throttleID && clearTimeout(fn._throttleID)
  fn._throttleID = setTimeout(function () {
    // 执行函数
    fn.apply(that, args)
  }, time)
}

// 去重
export const deDup = (array) => {
  return [...new Set([...array])]
}

// 数组对象去重
export const deDupArray = (array, key = 'id') => {
  const obj = {}
  const result = []
  array = deep(array)
  const len = array.length
  for (let i = len; i--; ) {
    const item = array[i]
    if (!obj[item[key]] && item[key]) {
      result.unshift(item)
      obj[item[key]] = true
    }
  }
  return result
}

// filter model 数据里面的值
export const findModelByKey = (v, modelKey, str = '', key = 'name') => {
  const array = model[modelKey] || []
  const item = array.find((i) => i.value + '' === v + '')
  if (item) {
    return item[key]
  }
  return str
}

// 计算今天明天 周几
export const getDateDesc = (v) => {
  const format = 'YYYY-MM-DD'
  const date = moment(v).format(format)
  const today = moment(new Date()).format(format)
  const tomorrow = moment(new Date()).add(1, 'days').format(format)

  if (date === today) {
    return '今天'
  }
  if (date === tomorrow) {
    return '明天'
  }
  const desc = '周'
  const weekday = ['日', '一', '二', '三', '四', '五', '六']
  const day = new Date(date).getDay()
  return desc + weekday[day]
}

// 计算今天 明 后天
export const dateDescfrt = (v, frt = 'MM-DD') => {
  const format = 'YYYY-MM-DD'
  const date = moment(v).format(format)
  const today = moment(new Date()).format(format)
  const tomorrow = moment(new Date()).add(1, 'days').format(format)

  if (date === today) {
    return '今天'
  }
  if (date === tomorrow) {
    return '明天'
  }
  return moment(v).format(frt)
}

// 时间转化格式
export const getDateFormat = (v, format = 'YYYY-MM-DD') => {
  return moment(v).format(format)
}

export const getDateWeek = (v) => {
  return getDateFormat(v, 'MM月DD日') + ' ' + getDateDesc(v)
}

// 经纬度计算距离 单位 千米 （高德地图算）
// export const getDistance1 = (lat1, lng1, lat2, lng2) => {
//   return (GDMap.getDistance(lat1, lng1, lat2, lng2) / 1000).toFixed(2)
// }
// 经纬度计算距离 单位 千米
export const getDistance = (lat1, lng1, lat2, lng2) => {
  if (!(lat1 && lng1 && lat2 && lng2)) {
    return -1
  }
  lat1 = +lat1
  lng1 = +lng1
  lat2 = +lat2
  lng2 = +lng2
  var radLat1 = (lat1 * Math.PI) / 180.0
  var radLat2 = (lat2 * Math.PI) / 180.0
  var a = radLat1 - radLat2
  var b = (lng1 * Math.PI) / 180.0 - (lng2 * Math.PI) / 180.0
  var s =
    2 *
    Math.asin(
      Math.sqrt(
        Math.pow(Math.sin(a / 2), 2) +
          Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)
      )
    )
  s = s * 6378.137 // EARTH_RADIUS;
  s = Math.round(s * 10000) / 10000
  return s
}

export const getDistanceTxt = (v) => {
  v = +v
  if (isNaN(v)) {
    return -1
  }
  if (v === -1) {
    return ''
  }
  if (v < 1) {
    return (v * 1000).toFixed(0) + 'm'
  } else if (v > 100) {
    return '>100km'
  } else {
    return v.toFixed(1) + 'km'
  }
}

// 数字列表如果是 NAN 时采取默认值
export const isNaNStr = (v, str = 0) => {
  v = (v + '').replace(/\,/g, '')
  v = +v
  if (isNaN(v)) {
    return str
  }
  return v
}

export const toFixed = (v, num = 2, isFloat = true) => {
  v = isNaNStr(v)
  const n = v.toFixed(num)
  return isFloat ? getNum(n) : v
}

// 百分比
export const percent = (v) => {
  v = isNaNStr(v)
  return (v * 1000) / 10 + '%' // 处理精度问题 0.07*100
}

export const getNum = (v) => {
  v = isNaNStr(v)
  return parseFloat(v)
}

// key down 降序  up 生序
export const sortList = (list, property, key = 'up') => {
  const array = deep(list)
  for (let len = array.length; len--; ) {
    array[len].oldIndex = len
  }
  array.sort((a, b) => {
    if (key === 'down') {
      return b[property] - a[property] || a.oldIndex - b.oldIndex
    }
    return a[property] - b[property] || a.oldIndex - b.oldIndex
  })
  return array
}

// 数组对象价格累加
export const arrayCalc = (array, priceKey, numKey) => {
  const len = array.length || 0
  let sum = 0
  for (let i = len; i--; ) {
    const item = array[i]
    const num = numKey ? item[numKey] : 1
    const price = priceKey ? item[priceKey] : item
    const value = isNaNStr(num) * isNaNStr(price)
    sum = sum + value
  }
  return sum
}

export const calcNumSum = (array = []) => {
  const t = array.reduce((total, num) => {
    return total + isNaNStr(num)
  }, 0)
  return t
}

// 重置数组对象的的值
export const resetArrayVal = (array, key, value = '') => {
  const len = array.length || 0
  for (let i = len; i--; ) {
    array[i][key] = value
  }
}

export const getTimeAgo = (o) => {
  var c = moment(o).valueOf()
  var n = new Date().getTime()
  var f = n - c
  var bs = f >= 0 ? '前' : '后' // 判断时间点是在当前时间的 之前 还是 之后
  f = Math.abs(f)
  if (f < 6e4) {
    return '刚刚'
  } // 小于60秒,刚刚
  if (f < 36e5) {
    return parseInt(f / 6e4) + '分钟' + bs
  } // 小于1小时,按分钟
  if (f < 864e5) {
    return parseInt(f / 36e5) + '小时' + bs
  } // 小于1天按小时
  if (f < 2592e6) {
    return parseInt(f / 864e5) + '天' + bs
  } // 小于1个月(30天),按天数
  //  if(f<31536e6){return parseInt(f/2592e6)+'个月'+bs}//小于1年(365天),按月数
  //  return parseInt(f/31536e6)+'年'+bs;//大于365天,按年算
  return o
}

// 图片预览
// export const imagePreview = (images, startPosition = 0) => {
//   window.imagePreview = ImagePreview({
//     images,
//     startPosition,
//     closeOnPopstate: true
//   })
// }

// obj1 的值覆盖到obj上 , （编辑表单时候用）
export const coverObj = (obj, obj1) => {
  const o = JSON.parse(JSON.stringify(obj))
  const o_key = Object.keys(o)
  o_key.forEach((el) => {
    o[el] = obj1[el] || o[el]
  })
  return o
}

export const handleNoCache = (noCache, to, from, next) => {
  // const path = from.path
  const path = auth.getFromPath() || from.path
  const white = ['/login', '/bindMobile'] // 必刷新入口
  const array = [...white, ...noCache]
  const sLocKeep = auth.sLoc.get('keep')
  const flag = array.includes(path) || sLocKeep === '1'
  auth.sLoc.remove('keep')
  flag && (to.meta.keep = flag)

  next()
}

export const qrcodeCreate = (content) => {
  return jrQrcode.getQrBase64(content)
}

// 获取基础url 地址
export const getBaseUrl = () => {
  const location = window.location
  return location.origin + location.pathname
}

// 获取数组中最小值
export const getMin = (array) => {
  const arr = array.map((i) => isNaNStr(i))
  return Math.min(...arr)
}

// 获取数组中最大值
export const getMax = (array) => {
  const arr = array.map((i) => isNaNStr(i))
  return Math.max(...arr)
}

// 数字向上取整
export const ceil = (v) => {
  const num = isNaNStr(v)
  return Math.ceil(num)
}

// 数字向下取整
export const floor = (v) => {
  const num = isNaNStr(v)
  return Math.floor(num)
}

// 解码参数
export const decodeQuery = (str) => {
  let s = str.replace(/zmgang/g, '/')
  s = s.replace(/zmqe/g, '=')
  s = s.replace(/zmque/g, '?')
  s = s.replace(/zmand/g, '&')
  return s
}

// 加密参数
export const encodeQuery = (str) => {
  let s = str.replace(/\//g, 'zmgang')
  s = s.replace(/=/g, 'zmqe')
  s = s.replace(/\?/g, 'zmque')
  s = s.replace(/&/g, 'zmand')
  return s
}

// 转译换行
export const toHtml = (v) => {
  if (!v) {
    return ''
  }
  v = v + ''
  // v = v.replace(/\\n/gm, '<br>')
  v = v.replace(/\n|\\n|↵/gm, '<br>')
  // v = v.replace(/↵/gm, '<br>')
  return v || ''
}

// 时间保留位数
export const time0 = (v) => {
  v = isNaNStr(v)
  v = '000000000000' + v
  return v.slice(-2)
}

export const submitForm = (action, method, param = {}) => {
  var dlform = document.createElement('form')
  dlform.style = 'display:none;'
  dlform.method = method.toLocaleUpperCase()
  dlform.action = action
  for (const i in param) {
    const hdnFilePath = document.createElement('input')
    hdnFilePath.type = 'hidden'
    hdnFilePath.name = i
    hdnFilePath.value = param[i]
    dlform.appendChild(hdnFilePath)
  }

  document.body.appendChild(dlform)
  dlform.submit()
  document.body.removeChild(dlform)
}

// 获取某一个值
export const getWidowValue = (key, target = window) => {
  return new Promise((resolve) => {
    function getStatus(resolve) {
      setTimeout(() => {
        if (target[key]) {
          resolve(target[key])
        } else {
          getStatus(resolve)
        }
      }, 200)
    }
    getStatus(resolve)
  })
}

export const handleUrl = (url) => {
  url = url || window.location.href
  const urls = url.split('#')
  let vuePath = urls[1]
  const basePath = urls[0]
  const joinStr = basePath.includes('?') ? '&' : '?'
  vuePath = encodeQuery(vuePath)
  return `${basePath}${joinStr}shareUrl=${vuePath}`
}

export const createShareUrl = (options) => {
  let link = options.link || ''
  const query = options.query || {}
  query.isShare = '1'
  const userInfo = auth.getLocUserInfo() || {}
  query.uId = userInfo.memberId || ''
  query.account = auth.getAccount()
  query.password = auth.getPwd()
  const queryStr = obj2Param(query)
  const sy = link.includes('?') ? '&' : '?'
  link = link + sy + queryStr
  link = '?shareUrl=' + encodeQuery(link)
  link = getBaseUrl() + link
  return link
}

export const mobileHide = (mobile) => {
  if (!mobile) {
    return ''
  }
  const m = mobile + ''
  return m.replace(/^(\d{3})\d{5}(\d+)/, '$1*****$2')
}

export const showDebug = () => {
  const vc = window.vc
  if (!vc) {
    window.vc = new VConsole()
  }
}

export const showDebugBuyUrl = () => {
  const url = window.location.href
  if (url.includes('debug=debug')) {
    showDebug()
  }
}

export const getElHeight = (dom) => {
  return dom ? dom.clientHeight || dom.offsetHeight : 0
}

export const isIOS = () => {
  const u = navigator.userAgent
  const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) // ios终端
  return isIOS
}

// 复制
export const copy = (value) => {
  return new Promise((resolve) => {
    const textarea = document.createElement('textarea')
    textarea.value = value
    textarea.style.position = 'absolute'
    textarea.style.top = '-9999px'
    document.body.appendChild(textarea)
    textarea.focus()
    textarea.select()
    document.execCommand('Copy')
    textarea.remove()
    resolve()
  })
}

export const arrayGruop = (arr, subGroupLength) => {
  const array = deep(arr)
  let index = 0
  const newArray = []
  while (index < array.length) {
    newArray.push(array.slice(index, (index += subGroupLength)))
  }
  return newArray
}

export const split = (value, slen = 3) => {
  const len = value.length
  const array = []
  for (var i = 0; i < len; i += slen) {
    array.push(value.slice(i, i + slen))
  }
  return array
}

export function replaceUrl(exp, val) {
  const url = window.location.href
    .replace(window.location.origin, '')
    .replace(exp, val)
  window.history.replaceState('', document.title, url)
}

export function preLoad(requireContext) {
  return requireContext.keys().map((src) => {
    const img = new Image()
    img.src = src
  })
}

// 移除地址栏search 参数
export function removeUrlParams(array = []) {
  if (array.length === 0) {
    return
  }
  const loc = window.location
  const search = loc.search
  const searchObj = param2Obj()
  array.forEach((key) => {
    if (key in searchObj) {
      delete searchObj[key]
      console.log('移除地址栏search 参数', key)
    }
  })
  const newSearch = obj2Param(searchObj) ? '?' + obj2Param(searchObj) : ''
  const url = window.location.href
    .replace(window.location.origin, '')
    .replace(search, newSearch)
  window.history.replaceState('', document.title, url)
}

export const abs = (v) => {
  return Math.abs(isNaNStr(v))
}
export const muiltipleImgLoaded = (imgs) => {
  const promiseAll = []
  const img = []
  for (let i = 0; i < imgs.length; i++) {
    promiseAll[i] = new Promise((resolve) => {
      img[i] = new Image()
      img[i].src = imgs[i]
      img[i].onload = function () {
        // 第i张加载完成
        resolve(img[i])
      }
    })
  }
  return promiseAll
}
export default {
  createShareUrl,
  arrayGruop,
  deep,
  param2Obj,
  obj2Param,
  lazyComponent,
  eachOwn,
  throttle,
  deDup,
  findModelByKey,
  deDupArray,
  getDateDesc,
  getDistance,
  calcNumSum,
  getDistanceTxt,
  sortList,
  getDateFormat,
  arrayCalc,
  resetArrayVal,
  getDateWeek,
  getTimeAgo,
  toFixed,
  isNaNStr,
  coverObj,
  getMin,
  getMax,
  decodeQuery,
  encodeQuery,
  getBaseUrl,
  toHtml,
  submitForm,
  ceil,
  time0,
  floor,
  getWidowValue,
  handleUrl,
  mobileHide,
  showDebug,
  showDebugBuyUrl,
  getElHeight,
  isIOS,
  replaceUrl,
  preLoad,
  sleep,
  removeUrlParams,
  abs,
  param2Obj1
}
